Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

audiofilters: Add Distortion effect #9776

Draft
wants to merge 7 commits into
base: main
Choose a base branch
from

Conversation

relic-se
Copy link

New audio effects class, audiofilters.Distortion, to distort audio samples using one of the available modes available in the audiofilters.DistortionMode enum.

Todo:

  • Reduce floating point computation overhead for DistortionMode.CLIP, DistortionMode.OVERDRIVE and DistortionMode.WAVESHAPE algorithms.
  • Test with unsigned and 8 bit sources.

Comments:

  • Should tone-shaping of some form be included within this class or require the use of an audiofilters.Filter effect? (ie: filter.play(distortion.play(sample)))
  • Any addition mode suggestions would be appreciated. The size overhead of including additional algorithms is very minimal. I'd only want to avoid redundant or unnecessary modes which may cause confusion (hence why I didn't include the ATAN mode within the Godot Engine).
  • The pre_gain and post_gain properties are currently measured in decibels which requires the addition of a db_to_linear function to make those values linear. Would it be more ideal to forego decibels altogether and make those properties linear?

Parameters, documentation copy and algorithms are mostly credited to Godot Engine under the MIT License.

Example Code:

import board
import audiobusio
import audiofilters
import audiocore
import digitalio
import adafruit_debouncer

audio = audiobusio.I2SOut(bit_clock=board.GP0, word_select=board.GP1, data=board.GP2)

wave_file = open("StreetChicken.wav", "rb")
wave = audiocore.WaveFile(wave_file)

effect = audiofilters.Distortion(
    buffer_size=1024,
    channel_count=wave.channel_count,
    sample_rate=wave.sample_rate,
    mix=0.0,
    pre_gain=0.0,
    post_gain=-10.0,
    drive=0.5,
)
effect.play(wave, loop=True)
audio.play(effect)

button_mix_pin = digitalio.DigitalInOut(board.GP3)
button_mix_pin.direction = digitalio.Direction.INPUT
button_mix = adafruit_debouncer.Debouncer(button_mix_pin)

button_mode_pin = digitalio.DigitalInOut(board.GP4)
button_mode_pin.direction = digitalio.Direction.INPUT
button_mode = adafruit_debouncer.Debouncer(button_mode_pin)

modes = [
#    (Mode, pre_gain, drive, post_gain),
    (audiofilters.DistortionMode.CLIP, 0.0, 0.5, -10.0),
    (audiofilters.DistortionMode.LOFI, 0.0, 0.9, -2.0),
    (audiofilters.DistortionMode.OVERDRIVE, 20.0, 0.5, -15.0),
    (audiofilters.DistortionMode.WAVESHAPE, 10.0, 0.75, -20.0),
]
mode_index = 0

# Initial state
print("off")
print(effect.mode)

while True:
    button_mix.update()
    if button_mix.rose:
        effect.mix = not effect.mix
        print("on" if effect.mix else "off")
    
    button_mode.update()
    if button_mode.rose:
        mode_index = (mode_index + 1) % len(modes)
        effect.mode, effect.pre_gain, effect.drive, effect.post_gain = modes[mode_index]
        print(effect.mode)

@RAWJUNGLE
Copy link

I think we need to add more fluff for the full effects package as well.

  • Maybe a bitcrasher?

@relic-se
Copy link
Author

I think we need to add more fluff for the full effects package as well.

* Maybe a bitcrasher?

I don't know exactly what you mean by "fluff", but the audiofilters.DistortionMode.LOFI is a bitcrusher. In fact, it may need to be renamed to better represent that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants